﻿using System.Collections.Generic;
using Data.NHibernateProvider;
using NHibernate.Criterion;

namespace Data.DataAccessObjects.Base
{
    public abstract class DaoBase<TEntity, TKeyType> : IDao<TEntity, TKeyType>
    {
        #region IDao<TEntity,TKeyType> Members

        public virtual IList<TEntity> GetAll()
        {
            return SessionProvider.MakeOperation(x => x.CreateCriteria(typeof(TEntity)).List<TEntity>());
        }

        public virtual int GetCount()
        {
            return
                (int)SessionProvider.MakeOperation(
                    x => x.CreateCriteria(typeof(TEntity)).SetProjection(Projections.RowCount()).UniqueResult());
        }

        public virtual TEntity GetById(TKeyType id)
        {
            return SessionProvider.MakeOperation(x => x.Get<TEntity>(id));
        }

        public virtual IList<TEntity> GetBy(string propertyName, object value)
        {
            return
                SessionProvider.MakeOperation(
                    x => x.CreateCriteria(typeof(TEntity)).Add(Restrictions.Eq(propertyName, value)).List<TEntity>());
        }

        public IList<TEntity> GetBy(string nestedName, string propertyName, object value)
        {
            return
                SessionProvider.MakeOperation(
                    x =>
                    x.CreateCriteria(typeof(TEntity)).CreateCriteria(nestedName).Add(Restrictions.Eq(propertyName,
                                                                                                      value)).List
                        <TEntity>());
        }

        public virtual TKeyType Save(TEntity entity)
        {
            return (TKeyType)SessionProvider.MakeOperationInTransaction(x => x.Save(entity));
        }

        public virtual void Update(TEntity entity)
        {
            SessionProvider.MakeOperationInTransaction(x => x.Update(entity));
        }

        public virtual void Delete(TEntity entity)
        {
            SessionProvider.MakeOperationInTransaction(x => x.Delete(entity));
        }

        public virtual void Refresh(TEntity entity)
        {
            SessionProvider.GetSession.Refresh(entity);
        }

        #endregion
    }
}